﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Nb.Common.Ioc
{
    public interface INbServiceRegistry<T>
    {
        Func<T> GetDefaultServiceFunc();
        void ResetDefaultServiceFunc(Func<T> func);
        IList<T> GetServices();
        T GetService();
    }

    public abstract class NbServiceRegistry<IService, ServiceRegistry> : INbServiceRegistry<IService> where ServiceRegistry : NbServiceRegistry<IService, ServiceRegistry>, new()
    {
        private Func<IService> _defaultFunc = null;
        private bool _needSearch = true;

        protected void Init()
        {
            var defaultServiceFunc = GetDefaultServiceFunc();
            if (defaultServiceFunc == null)
            {
                throw new InvalidOperationException("必须为具体的注册表类指定一个默认的服务");
            }
            _defaultFunc = defaultServiceFunc;
            _needSearch = true;
        }

        public abstract Func<IService> GetDefaultServiceFunc();

        public void ResetDefaultServiceFunc(Func<IService> func)
        {
            if (func == null)
            {
                throw new ArgumentNullException("func");
            }
            _defaultFunc = func;
            _needSearch = true;
        }

        public IList<IService> GetServices()
        {
            var allServices = new List<IService>();
            var service = _defaultFunc.Invoke();
            //log for default providers
            string defaultImplMessage = string.Format("default impl for {0} is {1}", typeof(IService).Name, service.GetType().Name);
            Log(defaultImplMessage);

            var serviceImpls = new List<IService>();
            if (_needSearch)
            {
                serviceImpls = CoreServiceProvider.Current.GetAllInstances<IService>().ToList();
                //Count > 0，意味着定义了其他的Provider
                //否则，下次没有机会在执行此代码块
                _needSearch = serviceImpls.Count > 0;
                //log for ioc providers
                Log(string.Format("CoreServiceProvider impls for {0} count => {1}", typeof(IService).Name, serviceImpls.Count));
                if (serviceImpls.Count > 0)
                {
                    allServices.AddRange(serviceImpls);
                }
            }

            //默认的提供，放在最后面
            allServices.Add(service);
            return allServices;
        }
        public IService GetService()
        {
            if (_defaultFunc == null)
            {
                throw new InvalidOperationException("调用前必须进行初始化Init()");
            }
            var services = GetServices();
            return services.First();
        }

        public static ServiceRegistry Instance
        {
            get
            {
                if (Singleton<ServiceRegistry>.Instance == null)
                {
                    Singleton<ServiceRegistry>.Instance = new ServiceRegistry();
                    Singleton<ServiceRegistry>.Instance.Init();
                }
                return Singleton<ServiceRegistry>.Instance;
            }
        }

        #region log

        //log
        private bool _logging = true;
        public void EnableLog(bool logging)
        {
            _logging = logging;
        }
        private void Log(string message)
        {
            if (_logging)
            {
                UtilsLogger.LogMessage(message);
            }
        }

        #endregion
    }
}
